package com.wetao.lib_common.tsdBlePen;


import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.provider.Settings;
import android.widget.Toast;

import com.alibaba.android.arouter.launcher.ARouter;
import com.tstudy.blepenlib.BlePenManager;
import com.tstudy.blepenlib.BlePenStreamManager;
import com.tstudy.blepenlib.callback.BleGattCallback;
import com.tstudy.blepenlib.callback.BlePenStreamCallback;
import com.tstudy.blepenlib.callback.BleScanCallback;
import com.tstudy.blepenlib.constant.Constant;
import com.tstudy.blepenlib.data.BleDevice;
import com.tstudy.blepenlib.data.CoordinateInfo;
import com.tstudy.blepenlib.exception.BleException;
import com.wetao.lib_common.ConstantArouter;
import com.wetao.lib_common.Constants;
import com.wetao.lib_common.EventBus.EventBusMessage;
import com.wetao.lib_common.EventBus.bean.SingleSwap_command;
import com.wetao.lib_common.EventBus.bean.SmallTest_command;
import com.wetao.lib_common.EventBus.bean.StudentJoinRoom_command;
import com.wetao.lib_common.EventBus.bean.TpData_command;
import com.wetao.lib_common.R;
import com.wetao.lib_common.base.BaseAppDeletage;
import com.wetao.lib_common.base.BaseListResponse;
import com.wetao.lib_common.base.BaseViewImp;
import com.wetao.lib_common.bean.request.StudentExamGridInfoReq;
import com.wetao.lib_common.bean.request.StudentExamGridInfoReq_vo;
import com.wetao.lib_common.bean.response.ExplainBean;
import com.wetao.lib_common.bean.response.StudentExamGridInfoResp;
import com.wetao.lib_common.bean.response.StudentExamGridInfoResp_grids;
import com.wetao.lib_common.bean.vo.PictureMore;
import com.wetao.lib_common.compare.ComparePenOffLinePage;
import com.wetao.lib_common.finalParam.GridSourceContentType;
import com.wetao.lib_common.finalParam.IsAnswerSheetType;
import com.wetao.lib_common.finalParam.PageSourceType;
import com.wetao.lib_common.greendao.DBUtils;
import com.wetao.lib_common.greendao.model.AnswerCard;
import com.wetao.lib_common.greendao.model.PenOffLineGridInfo;
import com.wetao.lib_common.greendao.model.PenOffLineGridInfoChild;
import com.wetao.lib_common.net.RetryWithDelay;
import com.wetao.lib_common.net.RxUtils;
import com.wetao.lib_common.net.ServerUtils;
import com.wetao.lib_common.net.callback.RequestCallback;
import com.wetao.lib_common.net.callback.RxErrorHandler;
import com.wetao.lib_common.utils.ComUtil;
import com.wetao.lib_common.utils.CompareUtil;
import com.wetao.lib_common.utils.DialogUtil;
import com.wetao.lib_common.utils.JsonUtils;
import com.wetao.lib_common.utils.LogUtils;
import com.wetao.lib_common.utils.SPUtils;
import com.wetao.lib_common.utils.ThreadUtils;
import com.wetao.lib_common.utils.ToastUtil;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import okhttp3.RequestBody;


public class TsdService extends Service {
    private final static String TAG = "TsdService";
    public static final String str_teacher_index_split = "&";

    public final static int ERR_TSD_PEN_INIT = 101; //蓝牙笔初始化错误
    public final static int ERR_TSD_GPS = 102; //位置服务没有打开
    public final static int ERR_TSD_BT_NO_SUPPORT = 103; //不支持蓝牙ble
    public final static int ERR_TSD_BT_NO_OPEN = 104; //蓝牙没有打开
    public final static int ERR_TSD_BT_OPEN_T = 105; //蓝牙打开成功
    public final static int ERR_TSD_BT_OPEN_F = 106; //蓝牙打开失败


    public final static int CONN_PEN_START = 201; //蓝牙连接开始；
    public final static int CONN_PEN_FAIL = 202; //蓝牙连接失败；
    public final static int CONN_PEN_SUCCESS = 203; //蓝牙连接成功；
    public final static int CONN_PEN_DIS = 204; //蓝牙取消连接；


    public final static byte PEN_COODINAT_MESSAGE = -114; //笔移动状态
    public final static byte PEN_DOWN_MESSAGE = -26;  //笔按下状态
    public final static byte PEN_UP_MESSAGE = -25;  //笔弹起状态
    public final static byte PEN_OTHER_MESSAGE = -24;  //笔其他状态

    public static final int MODULE_DEFAULT = 300; //默认无模式
    public static final int MODULE_HOMEWORK_CODE = 301; //点阵作业作答模式
    public static final int MODULE_HOMEWORK_LINE = 302; //在线作业作答模式
    public static final int MODULE_PEN_OFFLINE = 303; //笔的离线数据上传模式
    public static final int MODULE_ROOM = 304; //听课房间模式
    public static final int MODULE_SMALLTEST_DOT = 305; //课堂小测模式-点阵
    public static final int MODULE_SMALLTEST_LINE = 306; //课堂小测模式-在线
    public static final int MODULE_SINGLESWAP = 307; //答题互动模式(答题互动的主观题，客观题不需要进这个模式)
    public static final int MODULE_HOMEWORK_CODE_TUPU = 308;// 图谱点阵训练
    public static final int MODULE_HOMEWORK_LINE_TUPU = 309; //图谱在线作答模式
    public static final int MODULE_VIDEO = 310; //视频(包括图谱视频)
    public static final int MODULE_AUDIO = 311; //音频(包括图谱音频)
    public static final int MODULE_DOC = 312; //文档(包括图谱文档)
    private int mModule = MODULE_DEFAULT;

    public static final int ING_NO = 400;
    public static final int ING_HTTP = 401; //正在请求后台数据模式
    public static final int ING_ACTIVITY_SWITCH = 402; //正在切换界面模式
    private int mIng = ING_NO;


    private String mTsdServiceTag = null;
    private final IBinder mBinder = new LocalBinder();
    private boolean mIsTsbInitOk = false; //笔和蓝牙是否初始化成功
    private boolean mIsScaning = false; //正在搜索笔
    //private boolean mIsConnectOk = false; //笔是否连接
    public static BleDevice M_BLE_DEVICE; //通过这个参数来判断是否连接
    private int mFailReConnectCount = 0; //有时连接失败了，但是灯却是蓝色的。
    private BleGattCallback mBleGattCallback;
    private BlePenStreamCallback mBlePenStreamCallback;
    private BleScanCallback mScanCallback;
    private CoordinateInfo mCoordinateInfoTemp = null;
    private int mOfflineDataSize = 0;
    private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS", Locale.CHINA);

    private ConcurrentLinkedQueue<CoordinateInfo> mQDots = new ConcurrentLinkedQueue();
    private CoordinateInfo mCurDot = null;

    //小测命令
    private SmallTest_command mSmallTest_command;
    //房间命令
    private StudentJoinRoom_command mStudentJoinRoom_command;

    private StudentExamGridInfoReq mOffLineReq = new StudentExamGridInfoReq(2);
    private List<AnswerCard> mAnswerCard = new ArrayList<>();//记录所有答题卡的编号，暂时没有用到
    private List<PenOffLineGridInfo> mCurPageInfoList = new ArrayList<>();
    private CoordinateInfo mCurDotSamePage_tupu = null; //用于图谱每次点击都从后台获取数据
    private long mLastClick_tupu = 0; //用于图谱最后异常点击的时间
    private static final int MAX_CLICK_TIME = 60 * 1000; //防止频繁点击请求后台数据

    //private PenOffLineGridInfo mCur

    private boolean mJoinRoom = false;  //是否在房间里面，判断断网的情况

    private BluetoothStateBroadcastReceive mReceive; //监听蓝牙状态
    private LocationManager mLocationManager;//监听gps状态


    public List<AnswerCard> getmAnswerCard() {
        return mAnswerCard;
    }

    public boolean isHaveAnswerCard(String pageserial) {
        for (AnswerCard item : mAnswerCard) {
            if (pageserial.equals(item.getPageserial())) {
                return true;
            }
        }
        return false;
    }

    public void addAnswerCard(String pageserial) {
        if (!isHaveAnswerCard(pageserial)) {
            AnswerCard item = new AnswerCard(null, pageserial, null, null, null, null);
            mAnswerCard.add(item);
            DBUtils.getInstance(this).insertAnswerCard(item);
            DBUtils.getInstance(this).clearBuffer();
        }
    }

    public void initAnswerCard() {
        mAnswerCard = DBUtils.getInstance(this).getAnswerCard();
    }

    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    public class LocalBinder extends Binder {
        public TsdService getService() {
            return TsdService.this;
        }

        public void setTsdServiceTag(String className) {
            mTsdServiceTag = className;
            LogUtils.i("m1: mTsdServiceTag = " + mTsdServiceTag);
            if (onDataReceiveListener != null) {
                //onDataReceiveListener.onTestData(mTsdServiceTag);
            }
        }

        public void setTsdServiceConnected() {
            if (/*"com.wetao.module_pen.PenMainActivity".equals(mTsdServiceTag) && */!mIsTsbInitOk) {
                initTsdPen();
            } else {
                if (mIng == TsdService.ING_ACTIVITY_SWITCH) {
                }
                if (onDataReceiveListener != null) {
                }
                /*if(mIng == TsdService.ING_ACTIVITY_SWITCH && onDataReceiveListener != null) {
                    mIng = TsdService.ING_NO;
                    if(mCurDot != null) {
                        onDataReceiveListener.onCoordDraw(mCurDot);
                        pollDots();
                    }
                }*/
            }
        }

        public void on_rePenInit() {
            //比如打开蓝牙后，返回界面重新初始化
            initTsdPen();
        }

        public boolean on_isScaning() {
            return mIsScaning;
        }

        public void on_startScan() {
            if (mIsTsbInitOk) {
                if (!mIsScaning) {
                    BlePenStreamManager.getInstance().scan(mScanCallback);
                }
            } else {
                LogUtils.e("蓝牙笔 mIsTsbInitOk = false, 禁止调用搜索,并重新初始化");
                on_rePenInit();
            }
        }

        public void on_stopScan() {
            if (mIsTsbInitOk) {
                if (mIsScaning) {
                    BlePenStreamManager.getInstance().cancelScan();
                }
            } else {
                LogUtils.e("蓝牙笔 mIsTsbInitOk = false, 禁止调用搜索,并重新初始化");
                on_rePenInit();
            }
        }

        public void on_finishPre() {
            BlePenStreamManager.getInstance().cancelScan();
        }

        public void on_penConnect(BleDevice bleDevice) {
            if (mIsScaning) {
                BlePenStreamManager.getInstance().cancelScan();
            }
            Observable.timer(2000, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<Long>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(Long aLong) {
                            LogUtils.d("m1:onNext " + aLong + ", threadName = " + Thread.currentThread().getName());
                            mFailReConnectCount = 0;
                            BlePenStreamManager.getInstance().connect(bleDevice, mBleGattCallback, mBlePenStreamCallback);
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onComplete() {

                        }
                    });

        }

        public BleDevice on_getmBleDevice() {
            return M_BLE_DEVICE;
        }

        public void on_setmModule(int module) {
            setmModule(module);
        }

        public int on_getmModule() {
            return mModule;
        }

        public SmallTest_command on_getmSmallTest_command() {
            return mSmallTest_command;
        }

        public StudentJoinRoom_command on_getmStudentJoinRoom_command() {
            return mStudentJoinRoom_command;
        }

        public boolean on_getmJoinRoom() {
            return mJoinRoom;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        LogUtils.i("m1:TsdService onCreate");

        registerBluetoothReceiver();
        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        getContentResolver()
                .registerContentObserver(
                        Settings.Secure
                                .getUriFor(Settings.System.LOCATION_PROVIDERS_ALLOWED),
                        false, mGpsMonitor);



        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String CHANNEL_ID_STRING = "service_01";
            NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
            NotificationChannel mChannel = null;
            mChannel = new NotificationChannel(
                    CHANNEL_ID_STRING, getString(R.string.app_name),
                    NotificationManager.IMPORTANCE_LOW
            );
            notificationManager.createNotificationChannel(mChannel);
            Notification notification =
                    new Notification.Builder(this, CHANNEL_ID_STRING)
                            .setContentText("正在后天定位")
                            .build();
            startForeground(1, notification);
        }
        EventBus.getDefault().register(this);

        initAnswerCard();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtils.i("m1:TsdService onDestroy");

        EventBus.getDefault().unregister(this);
        if (mIsTsbInitOk && M_BLE_DEVICE != null && BlePenStreamManager.getInstance().isConnected(M_BLE_DEVICE)) {
            BlePenStreamManager.getInstance().disconnect(M_BLE_DEVICE);
        }


        unregisterBluetoothReceiver();
        getContentResolver().unregisterContentObserver(mGpsMonitor);


    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.i("m1:TsdService onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        LogUtils.i("m1:TsdService onBind");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        //close();
        LogUtils.i("m1:TsdService onUnbind");
        return super.onUnbind(intent);
    }

    private void initTsdPen() {
        boolean initSuccess = BlePenStreamManager.getInstance().init(this, MyLicense.getBytes());
        if (initSuccess) {
            BlePenStreamManager.getInstance().enableLog(true);
            initTsdPenListener();
            refreshGpsIsOpen();
        } else {
            Toast.makeText(this, "初始化失败，请到开放平台申请授权或检查设备是否支持蓝牙BLE", Toast.LENGTH_LONG).show();
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onErrTsdPen(ERR_TSD_PEN_INIT, "初始化失败，请到开放平台申请授权或检查设备是否支持蓝牙BLE");
            }
        }
    }

    private void refreshGpsIsOpen() {
        if(onDataReceiveListener == null) {
            return;
        }

        if (!gpsIsOpen() && onDataReceiveListener != null) {
            onDataReceiveListener.onErrTsdPen(ERR_TSD_GPS, "位置服务关闭，请点击打开");
            disconnectBlePen();
            mIsTsbInitOk = false;
        } else {
            checkBleOpen();
        }
    }

    private void checkBleOpen() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {
            onDataReceiveListener.onErrTsdPen(ERR_TSD_BT_NO_SUPPORT, "检查设备是否支持蓝牙BLE");
            disconnectBlePen();
            mIsTsbInitOk = false;
            return;
        }
        if (!bluetoothAdapter.isEnabled()) {
            onDataReceiveListener.onErrTsdPen(ERR_TSD_BT_NO_OPEN, "请先打开蓝牙");
            disconnectBlePen();
            mIsTsbInitOk = false;
            return;
        }

        onDataReceiveListener.onErrTsdPen(TsdService.ERR_TSD_BT_OPEN_T, "蓝牙打开成功");

        mIsTsbInitOk = true;
    }

    /**
     * 判断GPS是否开启，GPS或者AGPS开启一个就认为是开启的
     *
     * @return true 表示开启
     */
    public boolean gpsIsOpen() {
        LocationManager locationManager
                = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        // 通过GPS卫星定位，定位级别可以精确到街（通过24颗卫星定位，在室外和空旷的地方定位准确、速度快）
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean passive = locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
        // 通过WLAN或移动网络(3G/2G)确定的位置（也称作AGPS，辅助GPS定位。主要用于在室内或遮盖物（建筑群或茂密的深林等）密集的地方定位）
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        LogUtils.i("gpsIsOpen: gps" + gps + "    passive" + passive + "     network " + network);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //版本大于6.0，必须打开gps才可以搜索到蓝牙
            if (gps) {
                return true;
            }
        } else {
            //在版本低于此的时候，做一些处理
            if (gps || network || passive) {
                return true;
            }
        }
        return false;
    }

    private void disconnectBlePen() {
        if (M_BLE_DEVICE != null && mIsTsbInitOk && BlePenStreamManager.getInstance()!= null && BlePenStreamManager.getInstance().isConnected(M_BLE_DEVICE)) {
            BlePenStreamManager.getInstance().disconnect(M_BLE_DEVICE);
        }
    }


    private void initTsdPenListener() {
//通讯数据流回调
        mBlePenStreamCallback = new BlePenStreamCallback() {

            @Override
            public void onRemainBatteryAndMemory(final int batteryPercent, final int memoryPercent, final int memoryByteNum) {
                LogUtils.i("batteryPercent: " + batteryPercent + "%, memoryPercent: " + memoryPercent + "%, memoryByteNum:" + memoryByteNum + ", threadName = " + Thread.currentThread().getName());
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onGetPenInfo(batteryPercent, memoryPercent, memoryByteNum);
                }
            }

            @Override
            public void onCoordDraw(CoordinateInfo coordinateInfo) {
                /**
                 * 输出离线数据坐标信息
                 * @param state down/move/up
                 * @param pageAddress 点阵地址
                 * @param nX 坐标X
                 * @param nY 坐标Y
                 * @param nForce 压力值
                 * @param strokeNum 笔画数
                 * @param time 时间戳
                 * @param isOFFLine  是否是离线数据
                 * @param offLineDataAllSize 总离线字节数
                 * @param offLineDateCurrentSize 已上传字节数
                 */

                if (DialogUtil.getInstance().getmIsReLogin()) {
                    LogUtils.e("退出登录弹框，点击无效");
                    return;
                }
                LogUtils.i(", state: " + coordinateInfo.state
                        + ", strokeNum: " + coordinateInfo.strokeNum
                        + ", pageAddress: " + coordinateInfo.pageAddress
                        + ", coordForce: " + coordinateInfo.coordForce
                        + ", x: " + coordinateInfo.coordX
                        + ", y: " + coordinateInfo.coordY
                        + ", isOFFLine: " + coordinateInfo.isOFFLine
                        + ", offLineDataAllSize: " + coordinateInfo.offLineDataAllSize
                        + ", offLineDateCurrentSize: " + coordinateInfo.offLineDateCurrentSize
                        + ", timeLong: " + coordinateInfo.timeLong
                        + ", threadName = " + Thread.currentThread().getName()
                        + ",img =" + mIng
                );

                if(BaseAppDeletage.isRunInBackground) {
                    //程序运行在后台，点击无效
                    if (!mQDots.isEmpty()) {
                        mQDots.clear();
                    }
                    return;
                }

                /*if ("1536.714.72.88".equals(coordinateInfo.pageAddress)) {
                    //答题卡不要操作
                    return;
                }*/
                /*for(AnswerCard item : getmAnswerCard()) {
                    if(coordinateInfo.pageAddress.equals(item.getPageserial())) {
                        //答题卡不要操作
                        return;
                    }
                }*/

                //草稿纸，调用api/studentScreen/studentExam/pictrueGridInfo.json接口返回空数组

                /*if(coordinateInfo.state == TsdService.PEN_DOWN_MESSAGE) {
                    mOffLineReq.getGridInfoListVo().clear();
                    mOffLineReq.getGridInfoListVo().add(new StudentExamGridInfoReq_vo(coordinateInfo.pageAddress));
                    String json = JsonUtils.toJson(mOffLineReq);
                    studentExamGridInfo(json
                            , false, false);
                }
                if(true) {
                    return;
                }*/

                if (mCoordinateInfoTemp != null
                        && coordinateInfo.pageAddress != null
                        && coordinateInfo.coordX != 0
                        && coordinateInfo.coordY != 0
                        && coordinateInfo.state == TsdService.PEN_COODINAT_MESSAGE
                        && mCoordinateInfoTemp.state == TsdService.PEN_DOWN_MESSAGE) {
                    //按下点要重置坐标和地址，因为坐标可能是0，也可能是上一个点的弹起坐标，地址可能为null
                    //而且当前点必须是移动点，因为点击普通纸，也有单独的按下弹起点。
                    mCoordinateInfoTemp.pageAddress = coordinateInfo.pageAddress;
                    mCoordinateInfoTemp.coordX = coordinateInfo.coordX;
                    mCoordinateInfoTemp.coordY = coordinateInfo.coordY;
                    onCoordDraw_good(mCoordinateInfoTemp);
                }
                if (coordinateInfo.state == TsdService.PEN_DOWN_MESSAGE) {

                } else if (coordinateInfo.state == TsdService.PEN_UP_MESSAGE) {
                    if (mCoordinateInfoTemp.pageAddress != null
                            && mCoordinateInfoTemp.coordX != 0
                            && mCoordinateInfoTemp.coordY != 0
                            && mCoordinateInfoTemp.state == TsdService.PEN_COODINAT_MESSAGE) {
                        //弹起的坐标要重置，因为坐标为0，并且弹起前一个点必须是移动点，因为点击普通纸，有单独的按下弹起两点
                        coordinateInfo.coordX = mCoordinateInfoTemp.coordX;
                        coordinateInfo.coordY = mCoordinateInfoTemp.coordY;
                        onCoordDraw_good(coordinateInfo);
                    }
                } else {
                    onCoordDraw_good(coordinateInfo);
                }
                mCoordinateInfoTemp = coordinateInfo;

            }

            @Override
            public void onWarnActiveReport(int statusNum) {
                LogUtils.i("onWarnActiveReport, threadName = " + Thread.currentThread().getName());
                //0x05  电池电量低警告  0x08 存储空间警告
                switch (statusNum) {
                    case Constant.WARN_BATTERY:
                        LogUtils.i("handleActiveReport: 电池电量低警告");
                        break;
                    case Constant.WARN_MEMORY:
                        LogUtils.i("handleActiveReport: 存储空间警告");
                        break;
                    case Constant.WARN_BOOT_MODE:
                        LogUtils.i("handleActiveReport: WARN_BOOT_MODE");
                        break;
                    case Constant.WARN_APP_MODE:
                        LogUtils.i("handleActiveReport: WARN_APP_MODE");
                        break;
                    case Constant.WARN_VERIFY_MODE:
                        LogUtils.i("handleActiveReport: WARN_VERIFY_MODE");
                        //verifyPassword();
                        //Toast.makeText(mContext, "需要验证密码才能使用实时模式", Toast.LENGTH_LONG).show();
                        break;
                    case Constant.WARN_NOT_VERIFY_MODE:
                        LogUtils.i("handleActiveReport: WARN_NOT_VERIFY_MODE");
                        break;
                    default:
                }
            }

            @Override
            public void onNewSession(final String hardVersion, final String softVersion, final String syncNum) {
                //Version serial number
                LogUtils.i("hardVersion：" + hardVersion + ", softVersion:" + softVersion + ", syncNum:" + syncNum + ", threadName = " + Thread.currentThread().getName());

            }

            @Override
            public void onPenTimeOrPenOffTime(int statusNum, long penTime) {
                if (statusNum == 1) {
                    //如果与当前系统时间差一分钟以上，自动同步时间
                    long timeMillis = System.currentTimeMillis();
                    if (Math.abs(penTime - timeMillis) > 1000 * 60) {
                        BlePenStreamManager.getInstance().setPenRTC(timeMillis);
                    }
                    String formatTime = mSimpleDateFormat.format(new Date(penTime));
                    LogUtils.i("时间相差1分钟，formatTime = " + formatTime + ", threadName = " + Thread.currentThread().getName());

                } else if (statusNum == 2) {
                    String formatTime = mSimpleDateFormat.format(new Date(penTime));
                    LogUtils.i("关机时间，onPenTimeOrPenOffTime = " + formatTime + ", threadName = " + Thread.currentThread().getName());

                }
            }
        };

        //连接回调
        mBleGattCallback = new BleGattCallback() {
            @Override
            public void onStartConnect() {
                LogUtils.i("onStartConnect, threadName = " + Thread.currentThread().getName());
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onPenConnectStatus(CONN_PEN_START, null);
                }

                if (mIsScaning) {
                    //BlePenStreamManager.getInstance().cancelScan();
                }
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                LogUtils.i("onConnectFail, threadName = " + Thread.currentThread().getName());
                if (mFailReConnectCount < 2) {
                    mFailReConnectCount++;
                    Observable.timer(1000, TimeUnit.MILLISECONDS)
                            .observeOn(AndroidSchedulers.mainThread())
                            .subscribe(new Observer<Long>() {
                                @Override
                                public void onSubscribe(Disposable d) {

                                }

                                @Override
                                public void onNext(Long aLong) {
                                    LogUtils.d("m1:onNext " + aLong + ", threadName = " + Thread.currentThread().getName());
                                    BlePenStreamManager.getInstance().connect(bleDevice, mBleGattCallback, mBlePenStreamCallback);
                                }

                                @Override
                                public void onError(Throwable e) {

                                }

                                @Override
                                public void onComplete() {

                                }
                            });
                } else {
                    ToastUtil.initToast("智能笔连接失败！");
                    if (onDataReceiveListener != null) {
                        onDataReceiveListener.onPenConnectStatus(CONN_PEN_FAIL, bleDevice);
                    }
                    M_BLE_DEVICE = null;
                }
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice) {
                BlePenStreamManager.getInstance().setPenRTC(System.currentTimeMillis());
                LogUtils.i("onConnectSuccess, threadName = " + Thread.currentThread().getName());
                if (!ComUtil.isForeground(TsdService.this, "com.wetao.module_pen.PenMainActivity")) {
                    ToastUtil.initToast("智能笔连接成功！");
                }
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onPenConnectStatus(CONN_PEN_SUCCESS, bleDevice);
                }
                M_BLE_DEVICE = bleDevice;
                mOfflineDataSize = 0;
                EventBus.getDefault().post(new EventBusMessage(EventBusMessage.EVENT_BUS_ACTION_PEN_CONNECT_IS, "已连接"));
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice) {
                LogUtils.i("onDisConnected, threadName = " + Thread.currentThread().getName());
                ToastUtil.initToast("智能笔已断开！");
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onPenConnectStatus(CONN_PEN_DIS, bleDevice);
                }
                M_BLE_DEVICE = null;
                mCoordinateInfoTemp = null;
                EventBus.getDefault().post(new EventBusMessage(EventBusMessage.EVENT_BUS_ACTION_PEN_CONNECT_IS, "未连接"));
            }
        };

        //扫描回调
        mScanCallback = new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                LogUtils.i("onScanStarted, threadName = " + Thread.currentThread().getName());
                mIsScaning = true;
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onRefreshScan(mIsScaning);
                }
            }

            @Override
            public void onLeScan(BleDevice bleDevice) {
                super.onLeScan(bleDevice);
                LogUtils.i("onLeScan, threadName = " + Thread.currentThread().getName());
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                LogUtils.i("onScanning, threadName = " + Thread.currentThread().getName());
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onAddDevice(bleDevice);
                }
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                LogUtils.i("onScanFinished, threadName = " + Thread.currentThread().getName());
                mIsScaning = false;
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onRefreshScan(mIsScaning);
                }
            }
        };
    }

    private void onCoordDraw_good(CoordinateInfo coordinateInfo) {
        //直播课堂简答题
//        if (ComUtil.isForeground(TsdService.this, "com.newpage.module_classin.activity.AnswerActivity")) {
//            if (onDataReceiveListener != null) {
//                onDataReceiveListener.onCoordDraw(coordinateInfo);
//            }
//            return;
//        }

        if (ComUtil.isForeground(TsdService.this, "com.newpage.module_gather.activity.DrawActivity")) {
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onCoordDraw(coordinateInfo);
            }
            return;
        }
        if (ComUtil.isForeground(TsdService.this, "com.newpage.module_gather.activity.RevisionDrawActivity")) {
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onCoordDraw(coordinateInfo);
            }
            return;
        }


        if (coordinateInfo.isOFFLine) {
            //一连接马上就会有离线数据，这会儿还在连接界面，所以直接传值
            if (mOfflineDataSize == 0) {
                mOfflineDataSize = coordinateInfo.offLineDataAllSize;
            }
            if (mOfflineDataSize == coordinateInfo.offLineDataAllSize) {
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onCoordDraw(coordinateInfo);
                }
            }
        } else {
            //在线

            mQDots.offer(coordinateInfo);
            pollDots();
        }
    }


    private void pollDots() {
        if (mIng != TsdService.ING_NO) {
            LogUtils.i("m3: mIng" + "模式未初始化");
            return;
        }
        if (mQDots.isEmpty()) {
            return;
        }
        mCurDot = mQDots.poll();
        if (mCurDot == null || mCurDot.pageAddress == null) {
            pollDots();
            return;
        }
        if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
            mCurPageInfoList = DBUtils.getInstance(this).getPenOffLineGridInfoByPageserial(mCurDot.pageAddress);
            if (isToHttp()) {
                mCurDotSamePage_tupu = mCurDot;
                mLastClick_tupu = System.currentTimeMillis();

                mCurPageInfoList = new ArrayList<>();
                mOffLineReq.getGridInfoListVo().clear();
                mOffLineReq.getGridInfoListVo().add(new StudentExamGridInfoReq_vo(mCurDot.pageAddress));
                String json = JsonUtils.toJson(mOffLineReq);
                mIng = TsdService.ING_HTTP;
                studentExamGridInfo(json
                        , false, false);
            } else {
                mCurDotSamePage_tupu = mCurDot;
                mLastClick_tupu = System.currentTimeMillis();

                analysisCurDot();
            }
        } else {
            analysisCurDot();
        }
    }

    private boolean isToHttp() {
        if (mCurPageInfoList == null) {
            return true;
        }
        if (mCurPageInfoList.isEmpty()) {
            return true;
        }
        if (mCurPageInfoList.get(0).getPicId().intValue() == 0
                && mCurPageInfoList.get(0).getSourceType() == null) {
            return false;
        }
        if (mCurPageInfoList.get(0).getSourceType() != null
                && mCurPageInfoList.get(0).getSourceType().intValue() == PageSourceType.TUPU) {
            if (mCurDotSamePage_tupu == null) {
                return true;
            }
            if (!mCurDot.pageAddress.equals(mCurDotSamePage_tupu.pageAddress)) {
                return true;
            }
            boolean isTost = true;
            for (PenOffLineGridInfo gridInfo : mCurPageInfoList) {
                if (gridInfo.getGrids() == null) {
                    continue;
                }
                for (PenOffLineGridInfoChild child : gridInfo.getGrids()) {
                    float x = TsdPenUtil.getRealX(mCurDot.coordX, child.getBigPicWidth());
                    float y = TsdPenUtil.getRealY(mCurDot.coordY, child.getBigPicHeight());
                    if (x > child.getStartX().floatValue() && x < child.getEndX().floatValue() && y > child.getStartY().floatValue() && y < child.getEndY().floatValue()) {
                        isTost = false;
                        if (child.getContentType().intValue() == GridSourceContentType.DOT_TRAIN) {
                            return false;
                        } else {
                            break;
                        }
                    }
                }
            }

            if (System.currentTimeMillis() - mLastClick_tupu > TsdService.MAX_CLICK_TIME) {
                return true;
            }
            if (isTost) {
                //下面这些代码都是为了提示点击图片没有内容
                ToastUtil.initToast("暂未关联内容");
            }
        }
        return false;

    }

    private void analysisCurDot() {
        if (mCurPageInfoList == null || mCurPageInfoList.isEmpty()) {
            LogUtils.e("出错了，理论上，数据不能为空");
            return;
        }


        /**
         * 随堂互动 简答题
         */
        if (ComUtil.isForeground(TsdService.this, "com.newpage.module_classin.activity.AnswerActivity")
                && isAbleSingle()
                && mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_3){
            if (onDataReceiveListener!=null){
                onDataReceiveListener.onCoordDraw(mCurDot);
            }
            pollDots();
            return;
        }

        if (mCurPageInfoList.get(0).getSourceType() != null && mCurPageInfoList.get(0).getSourceType().intValue() == PageSourceType.TUPU) {
            //图谱
            if (isAbleToTupu()) {
                analysis_tp();
            } else {
                LogUtils.e("正在作答点阵教辅或者课堂，不能点击图谱");
                if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                    if (mModule == TsdService.MODULE_HOMEWORK_CODE) {
                        ToastUtil.initToast("正在作答点阵教辅，请勿点击图谱");
                    } else if (mModule == TsdService.MODULE_HOMEWORK_LINE) {
                        ToastUtil.initToast("正在作答在线训练，请勿点击图谱");
                    } else if (mModule == TsdService.MODULE_SMALLTEST_DOT) {
                        ToastUtil.initToast("正在作答点阵课堂小测，请勿点击图谱");
                    } else if (mModule == TsdService.MODULE_SMALLTEST_LINE) {
                        ToastUtil.initToast("正在作答在线课堂小测，请勿点击图谱");
                    } else if (mModule == TsdService.MODULE_ROOM || mModule == TsdService.MODULE_SINGLESWAP) {
                        ToastUtil.initToast("正在课堂互动中，请勿点击图谱");
                    }
                }
                pollDots();
            }
        } else {
            //草稿纸（sourceType == null） 或者 点阵教辅
            if (isAbleToDz()) {
                analysis_dz();
            } else {
                if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                    if(mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_1) {
                        ToastUtil.initToast("不能点击答题卡~");
                    }else if(mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_4) {
                        ToastUtil.initToast("不能点击智能作答本~");
                    }  else if (mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU) {
                        ToastUtil.initToast("正在作答图谱点阵训练，不能切换");
                    } else if (mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU) {
                        ToastUtil.initToast("正在作答图谱在线训练，不能切换");
                    } else {
                        LogUtils.e("正在作答图谱，不能点击教辅");
                    }
                }
                pollDots();
            }

        }
    }

    private void analysis_dz() {
        if (isAbleToHomework_dz()) {
            if (mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_2
                    && mCurPageInfoList.get(0).getSourceType() != null
                    && mCurPageInfoList.get(0).getSourceType() == PageSourceType.JIAOFU) {
                //教辅
                if (mIng == TsdService.ING_NO && !ComUtil.isForeground(TsdService.this, "com.wetao.module_homework.HomeworkCodeActivity")) {
                    //LogUtils.e("-----------------------isForeground----------");
                    mIng = TsdService.ING_ACTIVITY_SWITCH;
                    if (onDataReceiveListener != null) {
                        onDataReceiveListener.onFinish();
                        onDataReceiveListener = null;
                    }
                    ARouter.getInstance().build(ConstantArouter.PATH_HOMEWORK_CODEACTIVITY)
                            .navigation();
                    return;
                } else if (onDataReceiveListener != null) {
                    //LogUtils.e("-----------------------isForeground onDataReceiveListener != null----------");
                    mIng = TsdService.ING_NO;
                    onDataReceiveListener.onCoordDraw(mCurDot);
                }
            } else {
                //草稿纸
                if (mCurDot.state == PEN_DOWN_MESSAGE) {
                    ToastUtil.initToast("请在有效点阵教辅上作答");
                }
            }

        } else if (mModule == TsdService.MODULE_HOMEWORK_LINE
                || mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU) {
            if (mCurPageInfoList.get(0).getIsAnswerSheet().intValue()== IsAnswerSheetType.SHEET_TYPE_3) {
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onCoordDraw(mCurDot);
                }
            } else {
                ToastUtil.initToast("请在智能作答本上作答");
            }

        } else if (mModule == MODULE_SMALLTEST_DOT) {
            if (mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_2
                    && mCurPageInfoList.get(0).getSourceType() != null
                    && mCurPageInfoList.get(0).getSourceType() == PageSourceType.JIAOFU) {
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onCoordDraw(mCurDot);
                }
            } else {
                //草稿纸
                if (mCurDot.state == PEN_DOWN_MESSAGE) {
                    ToastUtil.initToast("请在有效点阵教辅上作答");
                }
            }

        } else if (mModule == MODULE_SMALLTEST_LINE) {
            if (mCurPageInfoList.get(0).getIsAnswerSheet().intValue()== IsAnswerSheetType.SHEET_TYPE_3) {
                if (onDataReceiveListener != null) {
                    onDataReceiveListener.onCoordDraw(mCurDot);
                }
            } else {
                ToastUtil.initToast("请在智能作答本上作答");
            }
        } else {
            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                if (mModule == TsdService.MODULE_ROOM
                        || mModule == TsdService.MODULE_SINGLESWAP) {
                    if (onDataReceiveListener != null){
                        onDataReceiveListener.onCoordDraw(mCurDot);
                    }
//                    ToastUtil.initToast("正在课堂中，请点击机点阵教辅");
                } else if (mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU) {
                    ToastUtil.initToast("正在作答图谱点阵训练，请勿点击点阵教辅");
                }
            }
        }
        pollDots();
    }

    private void analysis_tp() {
        for (PenOffLineGridInfo gridInfo : mCurPageInfoList) {
            for (PenOffLineGridInfoChild child : gridInfo.getGrids()) {
                float x = TsdPenUtil.getRealX(mCurDot.coordX, child.getBigPicWidth());
                float y = TsdPenUtil.getRealY(mCurDot.coordY, child.getBigPicHeight());
                if (x > child.getStartX().floatValue() && x < child.getEndX().floatValue() && y > child.getStartY().floatValue() && y < child.getEndY().floatValue()) {
                    switch (child.getContentType().intValue()) {
                        case GridSourceContentType.PDF_DOC: {
                            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                                if (isAbleToMedia()) {
                                    if (mModule == TsdService.MODULE_DOC) {
                                        //发广播，切换url(由activity自己判断url是否相同)
                                        whilePollUntileUp();
                                        TpData_command cm = new TpData_command(child.getGridId(), child.getQuestion(), child.getFileName());
                                        EventBus.getDefault().post(new EventBusMessage(EventBusMessage.EVENT_BUS_ACTION_DATA_TP, JsonUtils.toJson(cm)));

                                    } else {
                                        whilePollUntileUp();
                                        mIng = TsdService.ING_ACTIVITY_SWITCH;
                                        //开始activity， 切模式时，要关闭上一个模式的界面
                                        //onPuase时，将界面退出
                                        LogUtils.i("gridId = " + child.getGridId());
                                        LogUtils.i("fileUrl = " + child.getQuestion());
                                        LogUtils.i("title = " + child.getFileName());
                                        ARouter.getInstance().build(ConstantArouter.PATH_COMMON_TUPUPDFACTIVITY)
                                                .withInt("gridId", child.getGridId())
                                                .withString("fileUrl", child.getQuestion())
                                                .withString("title", child.getFileName())
                                                .navigation();
                                        delayPost(2000);
                                        return;
                                    }
                                } else {
                                    whilePollUntileUp();
                                }
                            }
                        }
                        break;
                        case GridSourceContentType.AUDIO: {
                            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                                if (isAbleToMedia()) {
                                    if (mModule == TsdService.MODULE_AUDIO) {
                                        //发广播，切换url(由activity自己判断url是否相同)
                                        whilePollUntileUp();
                                        TpData_command cm = new TpData_command(child.getGridId(), child.getQuestion(), child.getFileName());
                                        EventBus.getDefault().post(new EventBusMessage(EventBusMessage.EVENT_BUS_ACTION_DATA_TP, JsonUtils.toJson(cm)));
                                    } else {
                                        mIng = TsdService.ING_ACTIVITY_SWITCH;
                                        //开始activity;， 切模式时，要关闭上一个模式的界面
                                        //onPuase时，将界面退出
                                        whilePollUntileUp();
                                        ARouter.getInstance().build(ConstantArouter.PATH_COMMON_TUPUAUIOACTIVITY)
                                                .withInt("gridId", child.getGridId())
                                                .withString("url", child.getQuestion())
                                                .withString("name", child.getFileName())
                                                .navigation();
                                        delayPost(2000);
                                        return;
                                    }
                                } else {
                                    whilePollUntileUp();
                                }
                            }
                        }
                        break;
                        case GridSourceContentType.VIDEO: {
                            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                                if (isAbleToMedia()) {
                                    if (mModule == TsdService.MODULE_VIDEO) {
                                        //发广播，切换url(由activity自己判断url是否相同)
                                        whilePollUntileUp();
                                        TpData_command cm = new TpData_command(child.getGridId(), child.getQuestion(), child.getFileName());
                                        EventBus.getDefault().post(new EventBusMessage(EventBusMessage.EVENT_BUS_ACTION_DATA_TP, JsonUtils.toJson(cm)));
                                    } else {
                                        mIng = TsdService.ING_ACTIVITY_SWITCH;
                                        //开始activity;， 切模式时，要关闭上一个模式的界面
                                        ExplainBean curExplainBean = new ExplainBean();
                                        curExplainBean.setExplainName(child.getFileName());
                                        curExplainBean.setExplain_name(child.getFileName());
                                        curExplainBean.setExplainType(Constants.TYPE_VIDEO);
                                        curExplainBean.setExplainUrl(child.getQuestion());
                                        curExplainBean.setId(child.getGridId());
                                        whilePollUntileUp();
                                        ARouter.getInstance().build(ConstantArouter.PATH_LECTURE_LECTUREVIDEOACTIVITY)
                                                .withString("videoInfo", JsonUtils.toJson(curExplainBean))
                                                .withString("title", child.getFileName())
                                                .navigation();
                                        delayPost(3000);
                                        return;
                                    }
                                } else {
                                    whilePollUntileUp();
                                }
                            }
                        }
                        break;
                        case GridSourceContentType.LINE_TRAIN: {
                            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                                if (isAbleToMedia()) {
                                    if (mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU) {
                                        //在线作答不能相互切换
                                        whilePollUntileUp();
                                    } else {
                                        mIng = TsdService.ING_ACTIVITY_SWITCH;
                                        //开始activity;， 切模式时，要关闭上一个模式的界面
                                        whilePollUntileUp();
                                        ARouter.getInstance().build(ConstantArouter.PATH_HOMEWORK_LINEACTIVITY)
                                                .withString("examName", child.getExamName())
                                                .withInt("examId", child.getExamId())
                                                .withBoolean("mIsTupu", true)
                                                .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                                                .navigation();

                                        return;
                                    }
                                } else {
                                    whilePollUntileUp();
                                }
                            }

                        }
                        break;
                        case GridSourceContentType.DOT_TRAIN: {
                            if (isAbleToTupu_code()) {
                                if (mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU) {
                                    //绘制
                                    if (onDataReceiveListener != null) {
                                        onDataReceiveListener.onCoordDraw(mCurDot);
                                    }
                                } else {
                                    mIng = TsdService.ING_ACTIVITY_SWITCH;
                                    //开始activity;， 切模式时，要关闭上一个模式的界面
                                    ARouter.getInstance().build(ConstantArouter.PATH_HOMEWORK_CODEACTIVITY)
                                            .withBoolean("mIsTupu", true)
                                            .withInt("mExamId", child.getExamId())
                                            .withInt("mOutlineContentId", child.getKnowledgeMapOutlineContentId())
                                            .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
                                            .navigation();
                                    return;
                                }
                            } else {
                                whilePollUntileUp();
                            }

                        }
                        break;
                        default: {
                            LogUtils.e("没有找到指定类型，出错");
                            //pollDots();
                        }
                    }
                    pollDots();
                    return;
                }
            }
        }

    }

    private void delayPost(int time) {
        Observable.timer(time, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(Long aLong) {
                        LogUtils.d("m1:onNext " + aLong + ", threadName = " + Thread.currentThread().getName());
                        mIng = TsdService.ING_NO;
                        pollDots();
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void whilePollUntileUp() {
        while (!mQDots.isEmpty()) {
            CoordinateInfo info = mQDots.poll();
            if (info.state == TsdService.PEN_UP_MESSAGE) {
                break;
            }
            //循环弹出数据，直到弹出下一个弹起数据
        }
    }

    private boolean isAbleRoom() {
        if(mModule == TsdService.MODULE_ROOM
            || mModule == TsdService.MODULE_SMALLTEST_LINE
            || mModule == TsdService.MODULE_SMALLTEST_DOT
            || mModule == TsdService.MODULE_SINGLESWAP) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isAbleToTupu() {
        if (mModule == TsdService.MODULE_HOMEWORK_CODE
                || mModule == TsdService.MODULE_HOMEWORK_LINE
                || mModule == TsdService.MODULE_ROOM
                || mModule == TsdService.MODULE_SMALLTEST_DOT
                || mModule == TsdService.MODULE_SMALLTEST_LINE
                || mModule == TsdService.MODULE_SINGLESWAP) {
            return false;
        }
        return true;
    }

    //判断是否是单题 互动简答题或者错题订正
    private boolean isAbleSingle(){
        if (mModule == TsdService.MODULE_SINGLESWAP) {
            return true;
        }
        return false;
    }

    private boolean isAbleToDz() {
        if(mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_1
            || mCurPageInfoList.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_4) {
            //答题卡不进去
            return  false;
        } else if (mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU) {
            return false;
        } else if (mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU
                && mCurPageInfoList.get(0).getIsAnswerSheet().intValue() != IsAnswerSheetType.SHEET_TYPE_3) {
            return false;
        }
        return true;
    }

    private boolean isAbleToHomework_dz() {
        if (mModule == TsdService.MODULE_HOMEWORK_CODE
                || mModule == TsdService.MODULE_DEFAULT
                || mModule == TsdService.MODULE_VIDEO
                || mModule == TsdService.MODULE_AUDIO
                || mModule == TsdService.MODULE_DOC
        ) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isAbleToMedia() {
        if (mModule == TsdService.MODULE_DEFAULT
                || mModule == TsdService.MODULE_VIDEO
                || mModule == TsdService.MODULE_AUDIO
                || mModule == TsdService.MODULE_DOC
        ) {
            return true;
        } else {
            if (mModule == TsdService.MODULE_HOMEWORK_CODE) {
                ToastUtil.initToast("请先提交或退出当前教辅作答，否则不能切换");
            } else if (mModule == TsdService.MODULE_HOMEWORK_LINE) {
                ToastUtil.initToast("请先提交或退出当前在线作答，否则不能切换");
            } else if (mModule == TsdService.MODULE_PEN_OFFLINE) {
                ToastUtil.initToast("正在处理离线数据，不能切换");
            } else if (mModule == TsdService.MODULE_ROOM
                    || mModule == TsdService.MODULE_SINGLESWAP) {
                ToastUtil.initToast("正在课堂中，不能切换");
            } else if (mModule == TsdService.MODULE_SMALLTEST_DOT) {
                ToastUtil.initToast("请先提交或退出当前课堂小测，否则不能切换");
            } else if (mModule == TsdService.MODULE_SMALLTEST_LINE) {
                ToastUtil.initToast("请先提交或退出当前课堂小测，否则不能切换");
            } else if (mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU) {
                ToastUtil.initToast("请先提交或退出当前图谱点阵训练，否则不能切换");
            } else if (mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU) {
                ToastUtil.initToast("请先提交或退出当前图谱在线训练，否则不能切换");
            } else if (mModule == TsdService.MODULE_HOMEWORK_CODE) {
                ToastUtil.initToast("在课堂模式或作答模式下，不能切换");
            }

            return false;
        }
    }

    private boolean isAbleToTupu_code() {
        if (mModule == TsdService.MODULE_DEFAULT
                || mModule == TsdService.MODULE_VIDEO
                || mModule == TsdService.MODULE_AUDIO
                || mModule == TsdService.MODULE_DOC
                || mModule == TsdService.MODULE_HOMEWORK_CODE_TUPU
        ) {
            return true;
        } else {
            if (mCurDot.state == TsdService.PEN_DOWN_MESSAGE) {
                if (mModule == TsdService.MODULE_HOMEWORK_CODE) {
                    ToastUtil.initToast("请先提交或退出当前教辅作答，否则不能切换");
                } else if (mModule == TsdService.MODULE_HOMEWORK_LINE) {
                    ToastUtil.initToast("请先提交或退出当前在线作答，否则不能切换");
                } else if (mModule == TsdService.MODULE_PEN_OFFLINE) {
                    ToastUtil.initToast("正在处理离线数据，不能切换");
                } else if (mModule == TsdService.MODULE_ROOM
                        || mModule == TsdService.MODULE_SINGLESWAP) {
                    ToastUtil.initToast("正在课堂中，不能切换");
                } else if (mModule == TsdService.MODULE_SMALLTEST_DOT) {
                    ToastUtil.initToast("请先提交或退出当前课堂小测，否则不能切换");
                } else if (mModule == TsdService.MODULE_SMALLTEST_LINE) {
                    ToastUtil.initToast("请先提交或退出当前课堂小测，否则不能切换");
                } else if (mModule == TsdService.MODULE_HOMEWORK_LINE_TUPU) {
                    ToastUtil.initToast("请先提交或退出当前图谱在线训练，否则不能切换");
                } else if (mModule == TsdService.MODULE_HOMEWORK_CODE) {
                    ToastUtil.initToast("在课堂模式或作答模式下，不能切换");
                }
            }
            return false;
        }
    }

    public void studentExamGridInfo(String json, boolean isDialog, boolean cancelable) {
        RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), json);
        Observable<BaseListResponse<StudentExamGridInfoResp>> observable = null;
        observable = ServerUtils.getCommonApi().pictrueGridInfo(requestBody);
        observable.retryWhen(new RetryWithDelay(3, 2))
                //.compose(RxUtils.<BaseListResponse<StudentExamGridInfoResp>>bindToLifecycle(this))
                .compose(RxUtils.<BaseListResponse<StudentExamGridInfoResp>>getSchedulerTransformer())
                .subscribe(new RequestCallback<BaseListResponse<StudentExamGridInfoResp>>(this, RxErrorHandler.getInstance(), isDialog, cancelable) {
                    @Override
                    public void onNext(BaseListResponse<StudentExamGridInfoResp> baseResponse) {
                        super.onNext(baseResponse);
                        mCurPageInfoList.clear();
                        List<StudentExamGridInfoResp> list = baseResponse.getData();
                        if (baseResponse.getCode() == 0 && list != null) {
                            //数据入库
                            if (list.size() == 0) {
                                //说明点击的是草稿纸（作废，旧版本）
                                //表示铺了码，但是没有入库， 所有本地也不入库（新版本）
                                //需要删除就的数据库表中通用作答本中的内容。
                                /*PenOffLineGridInfo info = new PenOffLineGridInfo(null, 0, mCurDot.pageAddress, null, null, null, null
                                        , null, null, null, null, null, null, null, null,
                                        null, null, false, null, null, null, null, null, null
                                        , null, null, null, null, null, null, false, null
                                        , null, null, null);
                                DBUtils.getInstance(TsdService.this).insertPenOffLineGridInfo(
                                        info);
                                DBUtils.getInstance(TsdService.this).clearBuffer();*/

                                LogUtils.e("这一页有点码，但是没有入后台库，所以这一页不入本地库");
                                ToastUtil.initToast("暂未关联内容~");

                                whilePollUntileUp();
                                mIng = TsdService.ING_NO;
                                pollDots();
                                return;
                            } else {
                                if (isAbleSingle()){
                                    if(list.size() == 1
                                            && list.get(0).getIsAnswerSheet() != null
                                            && list.get(0).getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_3) {
                                        //在课堂简单题中，只能写通用作答本,并且只有通用作答本才入库
                                        gridInfoToDb(list);
                                    } else {
                                        mIng = TsdService.ING_NO;
                                        ToastUtil.initToast("请在作答本上进行作答");
                                        return;
                                    }
                                } else {
                                    gridInfoToDb(list);
                                }
                            }

                            mCurPageInfoList = DBUtils.getInstance(TsdService.this).getPenOffLineGridInfoByPageserial(mCurDot.pageAddress);
                            if (mCurPageInfoList == null || mCurPageInfoList.size() == 0) {
                                mCurPageInfoList = new ArrayList<>();
                                LogUtils.e("有可能没有话格子，所以没有入库");
                                ToastUtil.initToast("暂未关联内容~");
                            } else {
                                //下面这些代码都是为了提示点击图片没有内容
                                if (mCurPageInfoList.get(0).getSourceType() != null
                                        && mCurPageInfoList.get(0).getSourceType().intValue() == PageSourceType.TUPU) {
                                    boolean isTost = true;
                                    for (PenOffLineGridInfo gridInfo : mCurPageInfoList) {
                                        if (gridInfo.getGrids() == null) {
                                            continue;
                                        }
                                        for (PenOffLineGridInfoChild child : gridInfo.getGrids()) {
                                            float x = TsdPenUtil.getRealX(mCurDot.coordX, child.getBigPicWidth());
                                            float y = TsdPenUtil.getRealY(mCurDot.coordY, child.getBigPicHeight());
                                            if (x > child.getStartX().floatValue() && x < child.getEndX().floatValue() && y > child.getStartY().floatValue() && y < child.getEndY().floatValue()) {
                                                isTost = false;
                                                break;
                                            }
                                        }
                                        if (!isTost) {
                                            break;
                                        }
                                    }
                                    if (isTost) {
                                        ToastUtil.initToast("~暂未关联内容~");
                                    }
                                }
                            }
                            mIng = TsdService.ING_NO;
                            analysisCurDot();

                        } else {
                            //ToastUtil.initToast(baseResponse.getMsg());
                            LogUtils.e("请求后台获取页面数据失败1");
                            if (isAbleToTupu() && mModule == MODULE_SMALLTEST_LINE){
                                ToastUtil.initToast("正在作答随堂小测，不能点击图谱");
                            }
                            whilePollUntileUp();

                            mIng = TsdService.ING_NO;
                            pollDots();
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        super.onError(e);
                        ToastUtil.initToast(e.getMessage());
                        LogUtils.e("请求后台获取页面数据失败2");
                        whilePollUntileUp();
                        mIng = TsdService.ING_NO;
                        pollDots();
                    }
                });
    }

    private void gridInfoToDb(List<StudentExamGridInfoResp> resp) {
        for (int i = 0; i < resp.size(); i++) {
            StudentExamGridInfoResp item = resp.get(i);
            if (item.getId() == null) {
                LogUtils.e("m1: 没有图片id, 出错了");
                continue;
            }
            if (item.getSourceType() != null
                    && item.getSourceType().intValue() == PageSourceType.JIAOFU
                    && item.getIsAnswerSheet() != null
                    && item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_2
                    && item.getExamId() == null) {
                LogUtils.e("出错了， 教辅作答，必须要examId");
                continue;
            }
            /*if(item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_4) {
                //智能作答本暂时不考虑入库问题。
                LogUtils.e("-----------------智能作答本暂时不考虑入库问题");
                continue;
            }*/

            PenOffLineGridInfo info = DBUtils.getInstance(this).getPenOffLineGridInfoByPicId(item.getId());
            if (info == null) {

                if(item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_3) {
                    //通用作答本入库的方式不一样, 因为不需要入库grids
                    Long penOffLineGridInfoId = DBUtils.getInstance(this).insertPenOffLineGridInfo(
                            new PenOffLineGridInfo(null, item.getId(), item.getPageserial(), item.getBookId(), item.getOwnerNo(), item.getSectionNo(), item.getPageNumber()
                                    , item.getWidth(), item.getHeight(), item.getPictureUrl(), item.getSubjectCode(), item.getStatus()
                                    , item.getExamName(), item.getAssistantName(), item.getSubjectName(), item.getBookName(), item.getExamId()
                                    , false, 0f, 0f, 0f, 0f
                                    , 0f, 0f, 0f, 0f
                                    , ComUtil.getStringDate(), null, null, 1, false
                                    , item.getExamPageNumber(), item.getExamPageNo(), item.getIsAnswerSheet(), item.getSourceType()));
                    DBUtils.getInstance(this).clearBuffer();
                    continue;
                }
                if (item.getGrids() == null || item.getGrids().size() == 0) {
                    LogUtils.e("这一页有图片信息，但是没有格子，说明暂时没有传内容，暂时不入库");
                    //ToastUtil.initToast("这一页暂时没有上传格子内容");
                    continue;
                }
                boolean isMore = false; //这一页是否有多个课时
                for (int j = 0; j < resp.size(); j++) {
                    if (i != j
                            && item.getPageserial() != null
                            && item.getPageserial().equals(resp.get(j).getPageserial())) {
                        isMore = true;
                        break;
                    }
                }

                PictureMore pictureMore = new PictureMore();
                if (isMore) {
                    List<StudentExamGridInfoResp_grids> grids = item.getGrids();

                    for (StudentExamGridInfoResp_grids g : grids) {
                        pictureMore.setTemp1(g.getStartX(), g.getStartY(), g.getEndX(), g.getEndY(), g.getBigPicWidth(), g.getBigPicHeight());
                    }

                    LogUtils.e("计算格子设置范围步骤一：" + pictureMore.toString());
                    pictureMore.setTemp2(item.getWidth(), item.getHeight());
                    LogUtils.e("计算格子设置范围步骤二：" + pictureMore.toString());

                }
                //插入页信息
                Long penOffLineGridInfoId = DBUtils.getInstance(this).insertPenOffLineGridInfo(
                        new PenOffLineGridInfo(null, item.getId(), item.getPageserial(), item.getBookId(), item.getOwnerNo(), item.getSectionNo(), item.getPageNumber()
                                , item.getWidth(), item.getHeight(), item.getPictureUrl(), item.getSubjectCode(), item.getStatus()
                                , item.getExamName(), item.getAssistantName(), item.getSubjectName(), item.getBookName(), item.getExamId()
                                , isMore, pictureMore.startX_L, pictureMore.startY_L, pictureMore.endX_L, pictureMore.endY_L
                                , pictureMore.startX_R, pictureMore.startY_R, pictureMore.endX_R, pictureMore.endY_R
                                , ComUtil.getStringDate(), null, null, 1, false
                                , item.getExamPageNumber(), item.getExamPageNo(), item.getIsAnswerSheet(), item.getSourceType()));

                for (StudentExamGridInfoResp_grids item2 : item.getGrids()) {
                    //插入格子信息
                    DBUtils.getInstance(this).insertPenOffLineGridInfoChild(new PenOffLineGridInfoChild(null, item2.getGridId(), item2.getGridType(), item2.getPageserial()
                            , item2.getBookId(), item2.getPageNumber(), item2.getSectionNo(), item2.getOwnerNo(), item2.getPageNum()
                            , item2.getKnowledgeMapOutlineContentId(), item2.getContentType(), item2.getExamId(), item2.getExamName()
                            , item2.getIsExam(), item2.getQuestionId(), item2.getQuestion(), item2.getQuestionAnswer(), item2.getFileName()
                            , item2.getTotalPages(), item2.getDuration(), item2.getSetContent(), item2.getStartX(), item2.getStartY(), item2.getEndX(), item2.getEndY()
                            , item2.getClassId(), item2.getSourceNodeId(), item2.getSpreadFlag(), item2.getBigPicWidth(), item2.getBigPicHeight(), item2.getQuestionTypeId(), penOffLineGridInfoId));
                }
                DBUtils.getInstance(this).clearBuffer();

            } else {
                if(item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_1
                        || item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_3
                        || item.getIsAnswerSheet().intValue() == IsAnswerSheetType.SHEET_TYPE_4) {
                    //通用作答本，答题卡，不用检查更新
                    continue;
                }
                if (item.getGrids() == null || item.getGrids().size() == 0) {
                    LogUtils.e("这一页有图片信息，但是没有格子，说明暂时没有传内容，暂时不入库");
                    //ToastUtil.initToast("这一页暂时没有上传格子内容");
                    //删除表中数据
                    if (info.getGrids() != null || info.getGrids().size() > 0) {
                        for (PenOffLineGridInfoChild item_db : info.getGrids()) {
                            DBUtils.getInstance(this).deletePenOffLineGridInfoChild(item_db);
                        }
                    }
                    DBUtils.getInstance(this).deletePenOffLineGridInfo(info);
                    DBUtils.getInstance(this).clearBuffer();
                    continue;
                }
                //比较页信息
                if (ComparePenOffLinePage.comparePage(item, info)) {

                } else {
                    //如果页信息更新了，数据库更新
                    LogUtils.e("上次的是旧数据，更新了数据，重新入库");
                    info.setExamPageNumber(item.getExamPageNumber());
                    info.setExamPageNo(item.getExamPageNo());
                    info.setIsAnswerSheet(item.getIsAnswerSheet());
                    info.setSourceType(item.getSourceType());
                    info.setExamId(item.getExamId());
                    info.setExamName(item.getExamName());
                    info.setAssistantName(item.getAssistantName());
                    info.setBookName(item.getBookName());
                    DBUtils.getInstance(this).updatePenOffLineGridInfo(info);
                    DBUtils.getInstance(this).clearBuffer();
                }

                if (info.getGrids() == null || info.getGrids().size() == 0) {
                    //如果是旧数据，需要插入格子信息
                    LogUtils.e("上次的是旧数据，插入格子信息");
                    for (StudentExamGridInfoResp_grids item2 : item.getGrids()) {
                        DBUtils.getInstance(this).insertPenOffLineGridInfoChild(new PenOffLineGridInfoChild(null, item2.getGridId(), item2.getGridType(), item2.getPageserial()
                                , item2.getBookId(), item2.getPageNumber(), item2.getSectionNo(), item2.getOwnerNo(), item2.getPageNum()
                                , item2.getKnowledgeMapOutlineContentId(), item2.getContentType(), item2.getExamId(), item2.getExamName()
                                , item2.getIsExam(), item2.getQuestionId(), item2.getQuestion(), item2.getQuestionAnswer(), item2.getFileName()
                                , item2.getTotalPages(), item2.getDuration(), item2.getSetContent(), item2.getStartX(), item2.getStartY(), item2.getEndX(), item2.getEndY()
                                , item2.getClassId(), item2.getSourceNodeId(), item2.getSpreadFlag(), item2.getBigPicWidth(), item2.getBigPicHeight(), item2.getQuestionTypeId(), info.getId()));
                    }
                    DBUtils.getInstance(this).clearBuffer();
                } else {
                    //如果格子数据更新了，需要重新更新数据
                    if (ComparePenOffLinePage.comparePageGird(info.getGrids(), item.getGrids())) {

                    } else {
                        //后台数据跟本地数据库数据不相等，删除本地数据，重新插入
                        LogUtils.e("后台数据跟本地数据库数据不相等，删除本地数据，重新插入");
                        for (PenOffLineGridInfoChild item_db : info.getGrids()) {
                            DBUtils.getInstance(this).deletePenOffLineGridInfoChild(item_db);
                        }
                        DBUtils.getInstance(this).clearBuffer();
                        for (StudentExamGridInfoResp_grids item2 : item.getGrids()) {
                            DBUtils.getInstance(this).insertPenOffLineGridInfoChild(new PenOffLineGridInfoChild(null, item2.getGridId(), item2.getGridType(), item2.getPageserial()
                                    , item2.getBookId(), item2.getPageNumber(), item2.getSectionNo(), item2.getOwnerNo(), item2.getPageNum()
                                    , item2.getKnowledgeMapOutlineContentId(), item2.getContentType(), item2.getExamId(), item2.getExamName()
                                    , item2.getIsExam(), item2.getQuestionId(), item2.getQuestion(), item2.getQuestionAnswer(), item2.getFileName()
                                    , item2.getTotalPages(), item2.getDuration(), item2.getSetContent(), item2.getStartX(), item2.getStartY(), item2.getEndX(), item2.getEndY()
                                    , item2.getClassId(), item2.getSourceNodeId(), item2.getSpreadFlag(), item2.getBigPicWidth(), item2.getBigPicHeight(), item2.getQuestionTypeId(), info.getId()));
                        }
                        DBUtils.getInstance(this).clearBuffer();

                    }
                }

            }
        }
    }

    private void setmModule(int module) {
        setmModule(module, null);
    }

    private void setmModule(int module, String msg) {
        if (mModule != module) {
            mModule = module;
            LogUtils.e("当前处于的模式：" + mModule);
        }
    }

    private void exitBusRoom() {
        setmModule(TsdService.MODULE_DEFAULT, null);
    }

    private void exitBusAnswer() {
        //if(mModule == MODULE_SMALLTEST) {
        if (onDataReceiveListener != null) {
            onDataReceiveListener.onTeacherExitSmallTest();
        }
        //}
    }


    /// ===========================================================
    private OnDataReceiveListener onDataReceiveListener = null;

    public interface OnDataReceiveListener {
        void onErrTsdPen(int code, String msg);

        void onRefreshScan(boolean isScaning);

        void onAddDevice(BleDevice bleDevice);

        void onPenConnectStatus(int code, BleDevice bleDevice);

        void onGetPenInfo(int batteryPercent, int memoryPercent, int memoryByteNum);

        void onCoordDraw(CoordinateInfo coordinateInfo);

        void onFinish();//防止退出界面时，当前界面监听为null,导致很多问题

        void onTeacherExitSmallTest();
    }

    public void setOnDataReceiveListener(OnDataReceiveListener dataReceiveListener) {
        onDataReceiveListener = dataReceiveListener;
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void busGetMessage(EventBusMessage messageEvent) {
        /*if(true) {
            return;
        }*/
        LogUtils.i("m1: bus-->" + messageEvent.toString());
        int action = messageEvent.getAction();
        String msg = messageEvent.getMsg();
        if (action == EventBusMessage.EVENT_BUS_ACTION_TSDSERVICE_RESETDATA
                && msg != "com.wetao.module_homework.HomeworkLineActivity"
                && msg != "com.wetao.module_homework.HomeworkCodeActivity"
        ) {
            mQDots.clear();
            setmModule(MODULE_DEFAULT, msg);
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_ERROR) {
            stopSelf();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_ISROOM_EXIT) {
            //退出房间
            LogUtils.i("m1:退出听课房间");
            mJoinRoom = false;
            mQDots.clear();
            exitBusRoom();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_ANSWER_EXIT) {
            //退出答题互动或者退出课堂小测
            LogUtils.i("m1:退出课堂小测,或者退出答题互动");
            mQDots.clear();
            exitBusAnswer();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_ISROOM) {
            //进入听课房间
            if(isAbleRoom()) {
                return;
            }
            LogUtils.i("m1:进入听课房间");
            mJoinRoom = true;
            mQDots.clear();
            setmModule(MODULE_ROOM, msg);
            if (JsonUtils.isGoodJson(msg)) {
                try {
                    mStudentJoinRoom_command = JsonUtils.fromJson(msg, StudentJoinRoom_command.class);
                } catch (Exception e) {
                    LogUtils.e(e.getMessage());
                    e.printStackTrace();
                }
            } else {
                ToastUtil.initToast("房间命令不是正确的json字符串");
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_SMALLTEST) {

            //进入课堂小测
            LogUtils.i("m1:进入课堂小测");
            mQDots.clear();
            mSmallTest_command = null;
            //每次进入时将mModule设置为MODULE_HOMEWORK，否则第二次就如就无法进入循环内
            //mModule = MODULE_HOMEWORK;

            if (JsonUtils.isGoodJson(msg)) {
                try {
                    mSmallTest_command = JsonUtils.fromJson(msg, SmallTest_command.class);
                    int module = MODULE_DEFAULT;
                    if (mSmallTest_command.getIsLine().intValue() == 1) {
                        module = MODULE_SMALLTEST_LINE;
                    } else if (mSmallTest_command.getIsLine().intValue() == 2) {
                        module = MODULE_SMALLTEST_DOT;
                    }
                    setmModule(module, msg);
                    LogUtils.i("m1:得到小测命令对象-" + mSmallTest_command.toString());
                    //queryClassroomTestQuestionList();
                } catch (Exception e) {
                    LogUtils.e(e.getMessage());
                    e.printStackTrace();
                }
            } else {
                ToastUtil.initToast("小测命令不是正确的json字符串");
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_SMALLTEST_RETURN) {
            if (false) {
                /*if ("0".equals(msg)) {
                    //小测提交失败
                    mIsSubmitSuccess = false;
                    isSubmitSuccess();
                } else {
                    // 小测提交成功
                    isSubmitSuccess();
                }*/
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_WEBSOCKE_SINGLESWAP) {
            //进入答题互动 需要过滤主观题
            LogUtils.i("m1:进入答题互动 需要过滤主观题");
            mQDots.clear();
            boolean isSubject = false;
            if (JsonUtils.isGoodJson(msg)) {
                try {
                    SingleSwap_command singleSwap_command = JsonUtils.fromJson(msg, SingleSwap_command.class);
                    if (singleSwap_command != null && singleSwap_command.getQuestionType() != null && singleSwap_command.getQuestionType().intValue() == 3) {
                        isSubject = true;
                    }
                } catch (Exception e) {
                    LogUtils.e(e.getMessage());
                    e.printStackTrace();
                }

            }
            if (isSubject) {
                LogUtils.i("m1:进入答题互动主观题");
                setmModule(MODULE_SINGLESWAP, msg);
            } else {
                LogUtils.i("m1:进入答题互动客观题");
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_OUTLOGIN) {
            if (M_BLE_DEVICE != null && mIsTsbInitOk && BlePenStreamManager.getInstance().isConnected(M_BLE_DEVICE)) {
                BlePenStreamManager.getInstance().disconnect(M_BLE_DEVICE);
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_NOT_EXIT_ANSWER) {
            //websocket异常断开，正在重连，退出当前作答界面
            ToastUtil.initToast("直播课堂正在重连中~");
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onFinish();
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_AUDIO_INTO) {
            setmModule(MODULE_AUDIO, msg);
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_AUDIO_OUT) {
            if (mModule == MODULE_AUDIO) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_VIDEO_INTO) {
            setmModule(MODULE_VIDEO, msg);
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_VIDEO_OUT) {
            if (mModule == MODULE_VIDEO) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_DOC_INTO) {
            setmModule(MODULE_DOC, msg);
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_DOC_OUT) {
            if (mModule == MODULE_DOC) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_LINE_TUPU_INTO) {
            mIng = ING_NO;
            setmModule(MODULE_HOMEWORK_LINE_TUPU, msg);
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_LINE_TUPU_OUT) {
            if (mModule == MODULE_HOMEWORK_LINE_TUPU) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_CODE_TUPU_INTO) {
            mIng = ING_NO;
            setmModule(MODULE_HOMEWORK_CODE_TUPU, msg);
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onCoordDraw(mCurDot);
                pollDots();
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_CODE_TUPU_OUT) {
            if (mModule == MODULE_HOMEWORK_CODE_TUPU) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_CODE_INTO) {
            mIng = ING_NO;
            setmModule(MODULE_HOMEWORK_CODE, msg);
            if (onDataReceiveListener != null) {
                onDataReceiveListener.onCoordDraw(mCurDot);
                pollDots();
            }
        } else if (action == EventBusMessage.EVENT_BUS_ACTION_CODE_OUT) {
            if (mModule == MODULE_HOMEWORK_CODE) {
                mIng = ING_NO;
                setmModule(MODULE_DEFAULT, msg);
            }
            pollDots();
        }else if (EventBusMessage.EVENT_BUS_ACTION_ROOM_CONNECT_STATE == action){
            if ("false".equals(msg)){
                mJoinRoom = false;
            }else {
                mJoinRoom = true;
            }
        }
    }



    private void registerBluetoothReceiver(){
        if(mReceive == null){
            mReceive = new BluetoothStateBroadcastReceive();
        }
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_OFF");
        intentFilter.addAction("android.bluetooth.BluetoothAdapter.STATE_ON");
        registerReceiver(mReceive, intentFilter);
    }
    private void unregisterBluetoothReceiver(){
        if(mReceive != null){
            unregisterReceiver(mReceive);
            mReceive = null;
        }
    }
    class BluetoothStateBroadcastReceive extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            switch (action){
                case BluetoothDevice.ACTION_ACL_CONNECTED:
                    //Toast.makeText(context , "蓝牙设备:" + device.getName() + "已链接", Toast.LENGTH_SHORT).show();
                    break;
                case BluetoothDevice.ACTION_ACL_DISCONNECTED:
                    //Toast.makeText(context , "蓝牙设备:" + device.getName() + "已断开", Toast.LENGTH_SHORT).show();
                    break;
                case BluetoothAdapter.ACTION_STATE_CHANGED:{
                    ThreadUtils.doOnUIThread(new ThreadUtils.UITask() {
                        @Override
                        public void doOnUI() {
                            LogUtils.e("蓝牙状态改变了。。。。");
                            refreshGpsIsOpen();
                            int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
                            switch (blueState){
                                case BluetoothAdapter.STATE_OFF:
                                    Toast.makeText(context , "蓝牙已关闭", Toast.LENGTH_SHORT).show();
                                    break;
                                case BluetoothAdapter.STATE_ON:
                                    Toast.makeText(context , "蓝牙已开启"  , Toast.LENGTH_SHORT).show();
                                    break;
                            }
                        }
                    });
                }break;
            }
        }
    }

    private final ContentObserver mGpsMonitor = new ContentObserver(null) {
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            ThreadUtils.doOnUIThread(new ThreadUtils.UITask() {
                @Override
                public void doOnUI() {
                    boolean enabled = mLocationManager
                            .isProviderEnabled(LocationManager.GPS_PROVIDER);
                    LogUtils.e("GPS状态改变了。。。");
                    refreshGpsIsOpen();
                    if(enabled) {
                        Toast.makeText(TsdService.this , "gps已开启"  , Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(TsdService.this , "gps已开启"  , Toast.LENGTH_SHORT).show();
                    }
                }
            });
        }
    };

}

/**
 * 1，提交，没有图片显示， 后台加了在线作答背景导致的。
 * 2，更新后，重拉机制
 * 3，音量条
 * 4，pdf/doc无法显示
 * 6，音视频频繁切换
 * 7，点击作业会有toast弹框
 * 8，examId空和不空的区分
 * 9，草稿本问题，
 * 10，单题时间的提交问题
 * 11，在线作答切换工程的问题
 * 12，可能没有格子，但是有结构，格子和内容后续会传
 * 13,离线有问题
 * 14，离线提交或者删除后还是有列表数据
 * 15,平板ui兼容问题
 * 16,离线模式可能没有重置，导致无法点击
 * 17， 弹了toast,点做答延迟了，或没用
 * *
 */

